/**
 * Copyright (c) 2022 Beijing Jiaotong University
 * PhotLab is licensed under [Open Source License].
 * You can use this software according to the terms and conditions of the [Open Source License].
 * You may obtain a copy of [Open Source License] at: [https://open.source.license/]
 *
 * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 *
 * See the [Open Source License] for more details.
 *
 * Author: Qing'ao Zhang, Zhenjie Wei
 * Created: Mar. 15, 2023
 * Supported by: National Key Research and Development Program of China
 */

/* eslint-disable @typescript-eslint/no-explicit-any */

import { PhotOutput, PhotAnalyzerOutput, PhotTaskStatus } from "../thrift/gen-nodejs/engine_data_type_types"
import { PhotGraph } from "../thrift/gen-nodejs/graph_data_type_types"
import thriftClient from "../utils/conn"
import service from "../thrift/gen-nodejs/Engine"
import Int64 from "node-int64"

export default class EngineService {
    private _client: any
    constructor(socket: [string, number]) {
        this._client = thriftClient(service, socket[0], socket[1])
    }

    /**
     * Add a task to engine manager.
     * @param graph - The graph to be calculated.
     * @param taskId - The task id.
     * @param priority - The task priority.
     * @param executionTime - The task execution time.
     * @returns Add task response.
     */
    public async addTask(graph: PhotGraph, taskId: string, priority: number, executionTime: number) {
        return await this._client.add_task(graph, taskId, priority, new Int64(executionTime))
    }

    /**
     * Add a task from existing graph to engine manager.
     * @param graphName - The graph to be calculated.
     * @param taskId - The task id.
     * @param priority - The task priority.
     * @param executionTime - The task execution time.
     * @returns Add task response.
     */
    public async createTaskFromExistingGraph(
        graphName: string,
        taskId: string,
        priority: number,
        executionTime: number
    ) {
        return await this._client.create_task_from_existing_graph(graphName, taskId, priority, new Int64(executionTime))
    }

    /**
     * Engine calculate a task.
     * @param taskId - The task id to be calculated.
     * @returns Calculate task result response.
     */
    public async calculateTask(taskId: string) {
        return await this._client.calculate_task(taskId)
    }

    /**
     * Cancel a task to engine.
     * @param taskId - The task id.
     * @returns Cancel task response.
     */
    public async cancelTask(taskId: string) {
        return await this._client.cancel_task(taskId)
    }

    /**
     * Pause a task to engine.
     * @param taskId - The task id.
     * @returns Pause task response.
     */
    public async pauseTask(taskId: string) {
        return await this._client.pause_task(taskId)
    }

    /**
     * Recover a task.
     * @param taskId - The task id.
     * @returns Recover task response.
     */
    public async recoverTask(taskId: string) {
        return await this._client.recover_task(taskId)
    }

    /**
     * Recover a task.
     * @param taskId - The task id.
     * @returns Recover task response.
     */
    public async restartTask(taskId: string) {
        return await this._client.restart_task(taskId)
    }

    /**
     * Delete a task.
     * @param taskId - The task id.
     * @returns Delete task response.
     */
    public async deleteTask(taskId: string) {
        return await this._client.delete_task(taskId)
    }

    /**
     *
     * @param taskId
     * @param componentId
     * @returns
     */
    public async getComponentOutput(taskId: string, componentId: number): Promise<PhotOutput[]> {
        return await this._client.get_component_output(taskId, componentId)
    }

    /**
     *
     * @param taskId
     * @param componentId
     * @returns
     */
    public async getAnalyzerOutput(taskId: string, componentId: number): Promise<PhotAnalyzerOutput[]> {
        return await this._client.get_analyzer_output(taskId, componentId)
    }

    // /**
    //  *
    //  * @param taskId
    //  * @returns
    //  */
    // public async getAllComponentOutput(taskId: string): Promise<PhotOutput[]> {
    //     return await this._client.get_all_component_output(taskId)
    // }

    /**
     * Save a component result in a task
     * @param taskId - The task id.
     * @param componentId - The component id to be got output.
     * @param filePath - File path to output.
     * @returns The response of saving component output as.
     */
    public async saveComponentOutputAs(taskId: string, componentId: number, filePath: string) {
        return await this._client.save_component_output_as(taskId, componentId, filePath)
    }

    /**
     * TODO:
     * @param taskId
     * @param componentId
     * @param filePath
     * @returns
     */
    public async saveAnalyzerResultAs(taskId: string, componentId: number, filePath: string) {
        return await this._client.save_analyzer_result_as(taskId, componentId, filePath)
    }

    /**
     * Get a task status.
     * @param taskId - The task id.
     * @returns
     */
    public async getTaskStatus(taskId: string): Promise<PhotTaskStatus> {
        return await this._client.get_task_status(taskId)
    }

    /**
     *
     * @param taskId
     * @returns
     */
    public async getTaskExceptionInformation(taskId: string): Promise<string[]> {
        return await this._client.get_task_exception_information(taskId)
    }
}
